package com.example.scaffold.user.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.scaffold.common.bean.PageResult;
import com.example.scaffold.common.exception.BusinessException;
import com.example.scaffold.user.bean.UserDTO;
import com.example.scaffold.user.bean.UserEditParam;
import com.example.scaffold.user.bean.UserQueryParam;
import com.example.scaffold.user.bean.UserVO;
import com.example.scaffold.user.converter.UserConverter;
import com.example.scaffold.user.entity.User;
import com.example.scaffold.user.mapper.UserMapper;
import com.example.scaffold.user.service.UserService;
import lombok.RequiredArgsConstructor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import static com.example.scaffold.common.constant.RedisKeyConstant.USER_INFO_KEY;

/**
 * 用户服务实现类
 * 遵循阿里手册：服务实现类命名规范，缓存处理规范，事务管理规范
 *
 * @author example
 */
@Service
@RequiredArgsConstructor
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
    private static final Logger log = LoggerFactory.getLogger(UserServiceImpl.class);
    
    private final RedisTemplate<String, Object> redisTemplate;
    private final UserMapper userMapper;
    private final UserConverter userConverter;

    /**
     * 根据ID查询用户，使用缓存
     * 遵循阿里手册：缓存更新策略，缓存穿透防护
     */
    @Override
    public UserDTO getUserById(Long id) {
        if (id == null || id <= 0) {
            log.warn("查询用户ID不合法:{}", id);
            throw new BusinessException("用户ID不合法");
        }
        
        // 先查询缓存
        String cacheKey = String.format(USER_INFO_KEY, id);
        UserDTO userDTO = (UserDTO) redisTemplate.opsForValue().get(cacheKey);
        if (userDTO != null) {
            log.info("从缓存获取用户信息，用户ID:{}", id);
            return userDTO;
        }
        
        // 缓存未命中，查询数据库
        User user = getById(id);
        if (user == null) {
            log.warn("用户不存在，用户ID:{}", id);
            throw new BusinessException("用户不存在");
        }
        
        // 转换为DTO并缓存
        userDTO = BeanUtil.copyProperties(user, UserDTO.class);
        redisTemplate.opsForValue().set(cacheKey, userDTO, 30, TimeUnit.MINUTES);
        log.info("查询数据库并缓存用户信息，用户ID:{}", id);
        
        return userDTO;
    }

    /**
     * 创建用户，事务管理
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long createUser(UserEditParam param) {
        // 检查用户名是否已存在
        User existingUser = userMapper.selectByUsername(param.getUsername());
        if (existingUser != null) {
            log.warn("用户名已存在:{}", param.getUsername());
            throw new BusinessException("用户名已存在");
        }
        
        // 转换为实体
        User user = BeanUtil.copyProperties(param, User.class);
        user.setStatus(1); // 默认正常状态
        user.setDeleted(0); // 未删除
        user.setCreateTime(LocalDateTime.now());
        user.setUpdateTime(LocalDateTime.now());
        
        // 保存用户
        save(user);
        log.info("创建用户成功，用户ID:{}", user.getId());
        
        return user.getId();
    }

    /**
     * 更新用户，更新缓存
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateUser(Long id, UserEditParam param) {
        User user = getById(id);
        if (user == null) {
            log.warn("更新用户不存在，用户ID:{}", id);
            throw new BusinessException("用户不存在");
        }
        
        // 复制属性，忽略null值
        BeanUtil.copyProperties(param, user, "id", "createTime");
        user.setUpdateTime(LocalDateTime.now());
        
        // 更新数据库
        boolean result = updateById(user);
        
        // 更新缓存
        if (result) {
            String cacheKey = String.format(USER_INFO_KEY, id);
            UserDTO updatedDTO = BeanUtil.copyProperties(user, UserDTO.class);
            redisTemplate.opsForValue().set(cacheKey, updatedDTO, 30, TimeUnit.MINUTES);
            log.info("更新用户及缓存成功，用户ID:{}", id);
        }
        
        return result;
    }

    /**
     * 删除用户，删除缓存
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteUser(Long id) {
        // 逻辑删除
        // User user = new User();
        // user.setId(id);
        // user.setDeleted(1);
        // user.setUpdateTime(LocalDateTime.now());
        // boolean result = updateById(user);
        boolean result = removeById(id);
        
        // 删除缓存
        if (result) {
            String cacheKey = String.format(USER_INFO_KEY, id);
            redisTemplate.delete(cacheKey);
            log.info("删除用户及缓存成功，用户ID:{}", id);
        }
        
        return result;
    }

    @Override
    public PageResult<UserVO> listUser(UserQueryParam param) {
        IPage<User> page = new Page<>(param.getPageNum(), param.getPageSize());
        IPage<User> resultPage = userMapper.selectPage(page, null);
        List<UserVO> userVOs = resultPage.getRecords().stream()
                .map(userConverter::toVO)
                .collect(Collectors.toList());

        PageResult<UserVO> pageResult = new PageResult<>();
        pageResult.setTotal(resultPage.getTotal());
        pageResult.setPages(resultPage.getPages());
        pageResult.setPageNum(param.getPageNum());
        pageResult.setPageSize(param.getPageSize());
        pageResult.setList(userVOs);
        return pageResult;

    }
}
    